package com.zlx.store.user.interceptor;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zlx.store.common.constant.JWTSecurityKey;
import com.zlx.store.common.constant.RespCode;
import com.zlx.store.common.exception.TokenHasExpiredException;
import com.zlx.store.common.exception.UserNoLoginException;
import com.zlx.store.common.results.HttpResp;
import com.zlx.store.common.util.StringTool;
import com.zlx.store.domain.entity.StoreRelateUser;
import com.zlx.store.domain.entity.User;
import com.zlx.store.domain.entity.vo.TokenVO;
import com.zlx.store.user.dao.StoreRelateUserDao;
import com.zlx.store.user.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class JWTInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private UserDao userDao;
    @Autowired
    private StoreRelateUserDao storeRelateUserDao;

    /**
     * JWT的验证模块，应该在用户模块内加上加密密码，但目前已经简化为写死的加密密码
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        if (StringTool.isNull(token)) {
            throw new UserNoLoginException("未登录");
        }
        JWTSigner jwtSigner = JWTSignerUtil.hs256(JWTSecurityKey.SECURITY_KEY.key.getBytes(StandardCharsets.UTF_8));
//        boolean verify = JWTUtil.verify(token, jwtSigner);
        JWT jwt1 = JWTUtil.parseToken(token);
        boolean verify = jwt1.setKey(JWTSecurityKey.SECURITY_KEY.key.getBytes(StandardCharsets.UTF_8)).verify();
        if (verify) {
            Object o = redisTemplate.opsForValue().get(token);
            if (StringTool.isNull(o)) {
                throw new TokenHasExpiredException("登录过期");
            }
//            续期
            if (jwt1.validate(0)){
            TokenVO o1 = (TokenVO) o;
            User user = userDao.selectById(o1.getUserId());
            redisTemplate.delete(token);
            List<Long> storeIdList = storeRelateUserDao.selectList(
                            new LambdaQueryWrapper<StoreRelateUser>()
                                    .eq(StoreRelateUser::getUserId, user.getUserId())).stream()
                    .map(StoreRelateUser::getStoreId).collect(Collectors.toList());
            String jwt = JWT.create().setSigner(jwtSigner)
                    .setPayload("username", user.getUserName())
                    .setPayload("userId", user.getUserId())
                    .setPayload("userRole", user.getUserRole())
                    .setPayload("storeIds", storeIdList)
                    .setExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 30))
                    .sign();
            TokenVO tokenVO = new TokenVO().build(user, storeIdList);
            redisTemplate.opsForValue().set(jwt, tokenVO, 30, TimeUnit.MINUTES);
            response.getWriter().write(JSONObject.toJSONString(HttpResp.httpResp(RespCode.USER_LOGIN_SUCCESS, jwt, new Date())));
            response.getWriter().flush();
            return true;
        }}else {return true;}
        throw new TokenHasExpiredException("重新登陆，登录无效");
    }
}
